package crp.services.api.graphql;

import com.qwlabs.graphql.relay.Connection;
import com.qwlabs.graphql.relay.Relays;
import crp.core.security.app.RoleService;
import crp.core.security.domain.models.RoleQuery;
import crp.services.api.graphql.models.CreateRoleInput;
import crp.services.api.graphql.models.DeleteRoleInput;
import crp.services.api.graphql.models.RolePayload;
import crp.services.api.graphql.models.UpdateRoleInput;
import org.eclipse.microprofile.graphql.DefaultValue;
import org.eclipse.microprofile.graphql.GraphQLApi;
import org.eclipse.microprofile.graphql.Mutation;
import org.eclipse.microprofile.graphql.Query;

import javax.annotation.security.RolesAllowed;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.Optional;

import static crp.core.security.domain.models.Permissions.AUTH_ROLES_EDIT;

@GraphQLApi
@RequestScoped
@Transactional
public class RoleGraphQLApi {
    private final RoleService roleService;

    @Inject
    public RoleGraphQLApi(RoleService roleService) {
        this.roleService = roleService;
    }

    @Query
    @NotNull
    public Connection<RolePayload> roles(
            Optional<String> keyword,
            @DefaultValue("0") String after,
            @DefaultValue("10") Integer first) {
        var query = RoleQuery.custom()
                .range(Relays.of(after, first))
                .keyword(keyword.orElse(null))
                .build();
        return Relays.of(roleService.searcher().by(query), RolePayload::of);
    }

    @Mutation
    @NotNull
    @RolesAllowed(AUTH_ROLES_EDIT)
    public RolePayload updateRole(@NotNull @Valid UpdateRoleInput input) {
        return RolePayload.of(roleService.editor()
                .update(input.getId(), input.getName(), input.getPermissions()));
    }

    @Mutation
    @NotNull
    @RolesAllowed(AUTH_ROLES_EDIT)
    public RolePayload createRole(@NotNull @Valid CreateRoleInput input) {
        return RolePayload.of(roleService.editor()
                .create(input.getName(), input.getPermissions()));
    }

    @Mutation
    @NotNull
    @RolesAllowed(AUTH_ROLES_EDIT)
    public Boolean deleteRole(@NotNull @Valid DeleteRoleInput input) {
        roleService.editor().delete(input.getId());
        return true;
    }
}
